/********************************************************************
	created:	2008/05/30
	created:	30:5:2008   13:18
	filename: 	SkinWnd.h
	author:		Dean
	
	purpose:	
*********************************************************************/
#pragma once

class CIni;
class CSkinControl;
/*
 *	
 */
class CSkinWnd
{
public:
	CSkinWnd();
	virtual ~CSkinWnd(void);

	bool LoadSkin(CWnd* pWnd, LPCTSTR lpszSkinPath, LPCTSTR lpszSection);
	void	FreeSkin();
	void	UpdateWnd(UINT nID = 0);

	const CRect& GetClientRect() const		{ return m_rectClient;}
	LPCTSTR GetLogImage() const				{ return m_strLogImage; }
	COLORREF GetBackgroundColor() const			{ return m_crBackground; }
	
	LONG	OnEvent (LPCTSTR lpszCmd, const CComVariant& vEvent);
	// 
	BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
private:
	bool	LoadFrameImages(LPCTSTR lpszSection);
	UINT	CreatePanels(const CStringArray& PanelNames);
	UINT	CreateStatics(const CStringArray&);
	UINT	CreateIndicators(const CStringArray&);
	UINT	CreateButtons(const CStringArray& ButtonNames);
	UINT	CreateProgressCtrls(const CStringArray& ProgressCtrlNames);
private:
	class CPathAppend
	{
	public:
		CPathAppend(LPCTSTR lpszPath,  LPCTSTR lpszExtened) {
			if (NULL == lpszPath){
				::GetModuleFileName(AfxGetInstanceHandle(), m_szPath, _MAX_PATH);
				::PathRemoveFileSpec (m_szPath);
			}
			else{
				lstrcpy (m_szPath, lpszPath);
			}
			::PathAppend (m_szPath, lpszExtened);
		}
		~CPathAppend() {
			;
		}
		operator LPCTSTR() const {
			return m_szPath;
		}
	private:
		TCHAR m_szPath[_MAX_PATH];
	};

	class CInitGDIPlus
	{
	public:
		CInitGDIPlus(): m_dwToken( 0 ) {
			__try {
				InitializeCriticalSection(&m_sect);
				Init ();
			}
			__except( STATUS_NO_MEMORY == GetExceptionCode() ) {
				AtlThrow( E_OUTOFMEMORY );
			}
		}
		~CInitGDIPlus() {
			ReleaseGDIPlus();
			DeleteCriticalSection(&m_sect);
		}

		bool Init() {
			EnterCriticalSection(&m_sect);
			bool fRet = true;
			if ( m_dwToken == 0 ) {
				Gdiplus::GdiplusStartupInput input;
				Gdiplus::GdiplusStartupOutput output;
				Gdiplus::Status status = Gdiplus::GdiplusStartup( &m_dwToken, &input, &output );
				if ( status != Gdiplus::Ok )
					fRet = false;
			}
			LeaveCriticalSection(&m_sect);
			return fRet;
		}
		void ReleaseGDIPlus() {
			EnterCriticalSection(&m_sect);
			if ( m_dwToken != 0 ) {
				Gdiplus::GdiplusShutdown( m_dwToken );
			}
			m_dwToken = 0;
			LeaveCriticalSection(&m_sect);
		}
	private:
		ULONG_PTR m_dwToken;
		CRITICAL_SECTION m_sect;
	};
	static CInitGDIPlus s_initGDIPlus;
	static UINT			s_ControlId;

protected:
	CWnd*	m_pWnd;

	CString	m_strSkinPath;
	CIni*	m_pSkinConfigFile;
	CPoint	m_ptMinTrackSize;
	CRect	m_rectClient;
	CString	m_strLogImage;
	COLORREF m_crBackground;

	// frame images
	Gdiplus::Bitmap*	m_pImgs[9];
	Gdiplus::Bitmap*& m_pImgTopleft, *&m_pImgTop, *&m_pImgTopright;
	Gdiplus::Bitmap*& m_pImgLeft, *&m_pImgRight;
	Gdiplus::Bitmap*& m_pImgBottomleft, *&m_pImgBottom, *&m_pImgBottomright;
	Gdiplus::Bitmap*& m_pCacheFrameImage;

	// controls
	CTypedPtrList<CObList, CSkinControl*>	m_Controls;

	bool UpdateLayered(Gdiplus::Bitmap* pBmp);
	void RedrawWnd(const int cx, const int cy, const UINT nCtrlID = 0);
	bool DrawFrame(Gdiplus::Bitmap* pBmp, const int cxForm, const int cyForm);
	void DrawControls(Gdiplus::Bitmap* pBmp, UINT nCtrlID);

	//on windows message
	void OnSize(HWND hwnd, UINT state, int cx, int cy);
	void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
	void OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpMinMaxInfo);
};

